
#include<math.h>
#include<pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>

#include "Recv.h"
#include "Constant.h"
#include "ManageRoute.h"

int sockfd;
int recvCounter[256];
float neighbourRR[256];

char recvRouter[MAX_PACKET_LEN];
int recvLen;
pthread_mutex_t recv_mutex;

pthread_t p_id;
pthread_attr_t p_attr;

void cul_linkQuality();

void recv_init(){
	printf("recv_init\n");
	if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ){
	        perror("Recv_init---socket.");
	        printf("errno:%d\n",errno);
	        exit(1);
	    }

	int so_broadcast =1;
	setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &so_broadcast, sizeof(so_broadcast));

	struct sockaddr_in broadcast_addr;
	bzero(&broadcast_addr, sizeof(broadcast_addr));
	broadcast_addr.sin_family=AF_INET;
	broadcast_addr.sin_port = htons( BROADCASTPORT );
	if( inet_aton(BROADCASTIP,&broadcast_addr.sin_addr)<0 ){
	    perror("Recv_init---inet_aton.");
	    printf("errno:%d\n",errno);
	    //beep(2000,2000);
	    exit(1);
    }
    if( bind(sockfd,(struct sockaddr*)&broadcast_addr,sizeof(broadcast_addr))<0){
		perror("Recv_init---bind.");
		printf("errno:%d\n",errno);
		exit(1);
	}

	pthread_mutex_init(&recv_mutex, NULL);

	pthread_attr_init (&p_attr);
    pthread_attr_setdetachstate(&p_attr, PTHREAD_CREATE_DETACHED);
	if( pthread_create(&p_id,&p_attr,(void*)cul_linkQuality,NULL) !=0 ){
		//perror("beacon start error");
		printf("cul_linkQuality start error!%s\n",strerror(errno));
		//beep(2000,2000);
		abort();
		exit(1);
    }
}


void recv_departure(){
	sleep(2);
	printf("recv_departure\n");
	char tmp[200];
    char packet[MAX_PACKET_LEN];
    int len;
    int i=0;
    int j=0;
    struct sockaddr_in addr;
    size_t addrlen;
    memset(tmp,0,sizeof(tmp));
    while(1){
		if( (len=recvfrom(sockfd, packet, MAX_PACKET_LEN, 0, (struct sockaddr *)&addr, &addrlen))<0 ){
			perror("recv---recvfrom.");
			printf("errno:%d\n",errno);
		}
		else{
			strcpy(tmp, inet_ntoa(addr.sin_addr));
			if(strcmp(HOSTIP,tmp)!=0){//filter out the broadcast packets from itself.

			    int ID=0;
			    int tmplen = strlen(tmp);
			    for(i=tmplen-1,j=1; i>=0; i--){
					if(tmp[i]=='.')
					    break;
					else{
						ID=ID+(tmp[i]-'0')*j;
					}
					j=j*10;
				}

				if(ID!=0){//recv an broadcast packets
			        printf("recv---recvfrom %s:len=%d msg=%x\n",tmp,len,packet[1]);
			        pthread_mutex_lock( &recv_mutex);

			        updateRouter(ID, packet+1,len-1,neighbourRR);
                    recvCounter[ID]++;

                    pthread_mutex_unlock( &recv_mutex);
				}
			}
		}
	}
}


void cul_linkQuality(){
	//printf("cul_linkQuality---ID=%d\n",ID);

	int i=0;
	float RR;
    float NRR;
	//int len;
	//char tmpRouter[MAX_PACKET_LEN];
	int preEtx[256];
	memset(preEtx,0,sizeof(preEtx));
	while(1){
	    sleep(20);
	    pthread_mutex_lock( &recv_mutex);
	    for(i=0;i<256;i++){
			RR=recvCounter[i]/10.0;
                        recvCounter[i]=0;
            NRR=neighbourRR[i];
			neighbourRR[i]=NRR*0.5+RR*0.5;
			if(neighbourRR[i]>0 || RR>0 || NRR>0){
				printf("cul_linkQuality---ID=%d RR=%0.2f NRR=%0.2f neighbourRR[ID]=%0.2f\n",i,RR,NRR,neighbourRR[i]);
			}
		}
		printf("\n");
        pthread_mutex_unlock( &recv_mutex);
	}
}
